/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.google.code.japidiff;

import java.util.Map;
import java.util.HashMap;
import java.util.Collection;

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;

public class JavaClassBuilder implements ClassVisitor {

    private Map<String, JavaClass> classes = new HashMap<String, JavaClass>();
    private JavaClass clazz;
    private Map<String, String> innerClasses = new HashMap<String, String>();

    public Collection<JavaClass> getClasses() {
        for (Map.Entry<String, String> entry : innerClasses.entrySet()) {
            JavaClass inner = classes.get(entry.getKey());
            JavaClass outer = classes.get(entry.getValue());
            if (inner != null && outer != null) {
                outer.addInnerClass(inner);
            } else {
                //System.out.println("Can not process inner class: " + entry.getKey() + " -> " + entry.getValue());
            }
        }
        innerClasses.clear();
        return classes.values();
    }

    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
        clazz = new JavaClass(version, access, name, signature, superName, interfaces);
    }

    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
        JavaAnnotation anno = new JavaAnnotation();
        anno.setDesc(desc);
        anno.setVisible(visible);
        this.clazz.addAnnotation(anno);
        return new JavaAnnotationBuilder(anno);
    }

    public void visitAttribute(Attribute attribute) {
        clazz.addAttribute(attribute);
    }

    public void visitEnd() {
        classes.put(clazz.getName(), clazz);
        clazz = null;
    }

    public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
        JavaField field = new JavaField(access, name, desc, signature, value);
        clazz.addField(field);
        return new JavaFieldBuilder(field);
    }

    public void visitInnerClass(String name, String outerName, String innerName, int access) {
        innerClasses.put(name, outerName);
    }

    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
        JavaMethod method = new JavaMethod(access, name, desc, signature, exceptions);
        clazz.addMethod(method);
        return new JavaMethodBuilder(method);
    }

    public void visitOuterClass(String owner, String name, String desc) {
        //System.out.println("visitOuterClass [owner=" + owner + ", name=" + name + ", desc=" + desc + "]");
    }

    public void visitSource(String source, String debug) {
    }
}
